using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using ZSW.Framework.Utils;

namespace ZSW.Framework.Net
{
    public enum RequestMethod
    {
        GET,
        POST,
        PUT,
        DELETE
    }

    public class RequestResult
    {

    }

    public class ZSWF_WebRequest
    {
        private Dictionary<string, string> m_headers = new Dictionary<string, string>();
        private static bool m_isDebug = true;
        private ZSWF_WebRequestPool m_webRequestPool;
        public ZSWF_WebRequest(Dictionary<string, string> headers)
        {
            m_headers = headers;
            m_webRequestPool = new ZSWF_WebRequestPool();
        }

        public void SetHeader(string name, string value)
        {
            if (m_headers.ContainsKey(name))
            {
                m_headers[name] = value;
            }
            else
            {
                m_headers.Add(name, value);
            }
        }

        public void RemoveHeader(string name)
        {
            if (m_headers.ContainsKey(name))
            {
                m_headers.Remove(name);
            }
        }

        public UnityWebRequest GenerateWebClient(string uri, RequestMethod method)
        {
            if (m_webRequestPool == null)
            {
                m_webRequestPool = new ZSWF_WebRequestPool();
            }


            UnityWebRequest webRequest = m_webRequestPool.Get();
            webRequest.uri = new Uri(uri);
            webRequest.method = method.ToString();
            foreach (var header in m_headers)
            {
                webRequest.SetRequestHeader(header.Key, header.Value);
            }
            return webRequest;
        }


        public IEnumerator Get<T>(string uri, Action<T> callback) where T : RequestResult
        {
            UnityWebRequest webReuqest = GenerateWebClient(uri, RequestMethod.GET);
            webReuqest.downloadHandler = new DownloadHandlerBuffer();
            yield return webReuqest.SendWebRequest();

            if (!isError(webReuqest, RequestMethod.GET))
            {
                string result = webReuqest.downloadHandler.text;
                callback?.Invoke(JsonConvert.DeserializeObject<T>(result));
            }

            m_webRequestPool.Release(webReuqest);
        }

        public IEnumerator Post<T>(string uri, Action<T> callback, object value = null) where T : RequestResult
        {
            // HTTP请求
            UnityWebRequest webReuqest = GenerateWebClient(uri, RequestMethod.POST);

            string jsonStr = JsonConvert.SerializeObject(value);
            webReuqest.downloadHandler = new DownloadHandlerBuffer();
            webReuqest.uploadHandler = new UploadHandlerRaw(System.Text.Encoding.UTF8.GetBytes(jsonStr));

            yield return webReuqest.SendWebRequest();

            if (!isError(webReuqest, RequestMethod.POST))
            {
                string result = webReuqest.downloadHandler.text;
                callback?.Invoke(JsonConvert.DeserializeObject<T>(result));
            }
            else
            {
                callback?.Invoke(null);
            }


            // // 测试环境
            // float time = UnityEngine.Random.Range(0f, 1f);
            // // ZSWFUtil_Debug.Log(GetType().ToString(), $"等待{time}秒");
            // yield return new WaitForSeconds(time);
            // // ZSWFUtil_Debug.Log(GetType().ToString(), $"传入数值：{value.ToString()}");
            // string result = HttpRequestTest.Instance.GetResult(value.ToString());
            // // ZSWFUtil_Debug.Log(GetType().ToString(), $"获取Json{result.ToString()}");
            // var res = JsonConvert.DeserializeObject<T>(result);
            // // ZSWFUtil_Debug.Log(GetType().ToString(), "解析数据成功:" + res.ToString());
            // callback?.Invoke(res);


            m_webRequestPool.Release(webReuqest);
        }

        public IEnumerable Put<T>(string uri, Action callback, string data)
        {
            UnityWebRequest webReuqest = UnityWebRequest.Put(uri, data);

            yield return webReuqest.SendWebRequest();

            if (!isError(webReuqest, RequestMethod.PUT))
            {
                callback?.Invoke();
            }

            m_webRequestPool.Release(webReuqest);

        }
        public IEnumerable Put<T>(string uri, Action callback, byte[] data)
        {
            UnityWebRequest webReuqest = UnityWebRequest.Put(uri, data);

            yield return webReuqest.SendWebRequest();

            if (!isError(webReuqest, RequestMethod.PUT))
            {
                callback?.Invoke();
            }

            m_webRequestPool.Release(webReuqest);
        }
        public IEnumerator GetTexture(string uri, Action<Texture> callback)
        {
            UnityWebRequest webReuqest = UnityWebRequestTexture.GetTexture(uri);

            yield return webReuqest.SendWebRequest();

            if (!isError(webReuqest, RequestMethod.GET))
            {
                Texture texture = ((DownloadHandlerTexture)webReuqest.downloadHandler).texture;
                callback?.Invoke(texture);
            }

            m_webRequestPool.Release(webReuqest);

        }
        public IEnumerator GetAssetBundle(string uri, Action<AssetBundle> callback)
        {
            UnityWebRequest webReuqest = UnityWebRequestAssetBundle.GetAssetBundle(uri);

            yield return webReuqest.SendWebRequest();

            if (!isError(webReuqest, RequestMethod.GET))
            {
                AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(webReuqest);
                callback?.Invoke(bundle);
            }

            m_webRequestPool.Release(webReuqest);
        }

        private static bool isError(UnityWebRequest webReuqest, RequestMethod httpMethod)
        {
            switch (webReuqest.result)
            {
                case UnityWebRequest.Result.ConnectionError:
                    log(httpMethod.ToString(), "ConnectionError", webReuqest.error);
                    return true;
                case UnityWebRequest.Result.ProtocolError:
                    log(httpMethod.ToString(), "ProtocolError", webReuqest.error);
                    return true;
                case UnityWebRequest.Result.DataProcessingError:
                    log(httpMethod.ToString(), "DataProcessingError", webReuqest.error);
                    return true;
                case UnityWebRequest.Result.Success:
                    string result = webReuqest.downloadHandler.text;
                    log(httpMethod.ToString(), "Sucess", result);
                    return false;
                default:
                    return true;
            }
        }

        private static void log(string logType, string res, string content)
        {
            if (m_isDebug)
            {
                Debug.Log($"[{logType}][{res}] {content}");
            }
        }

    }
}
